﻿using System;
using System.Threading;
using HighDiveAdmin.Handlers;
using HighDiveEngine.Aggregates;
using HighDiveEngine.Model;
using HighDiveEngine.Resources;
using NUnit.Framework;

namespace UnitTestHighDive
{
    [TestFixture]
    public class UnitTestDbHandler
    {
        [Test]
        public void DbHandlerInitTest()
        {
            Assert.IsNotNull(DbHandler.Instance);
        }

        [Test]
        public void DbHandlerSaveContestClearLists()
        {
            UnitTestMockObjects._contest1.DiveHistory = new DiveList();
            UnitTestMockObjects._contest1.DiveQueue = new DiveList();

            DbHandler.Instance.SaveCompleteContestToDb(UnitTestMockObjects._contest1);
            var ds = DbHandler.Instance.DbEngine.SqlQuery("SELECT * FROM Contests;").Rows;

            Assert.AreEqual(1, ds.Count);
            Assert.AreEqual(UnitTestMockObjects._contest1.Name, (string)ds[0]["Name"]);
            Assert.AreEqual(UnitTestMockObjects._contest1.Country, (string)ds[0]["Country"]);
            Assert.AreEqual(UnitTestMockObjects._contest1.City, (string)ds[0]["City"]);
            Assert.AreEqual(UnitTestMockObjects._contest1.Club, (string)ds[0]["Club"]);
            Assert.AreEqual(UnitTestMockObjects._contest1.Date, (string)ds[0]["Date"]);
            Assert.AreEqual(UnitTestMockObjects._contest1.JudgeList.NumberOfJudges, Convert.ToInt32(ds[0]["NumJudges"]));
            Assert.AreEqual(UnitTestMockObjects._contest1.Status, (ContestStatus)Enum.Parse(typeof(ContestStatus), (string)ds[0]["Status"]));

            Assert.AreEqual(3, DbHandler.Instance.DbEngine.SqlQuery("SELECT * FROM Judges;").Rows.Count);
            Assert.AreEqual(0, DbHandler.Instance.DbEngine.SqlQuery("SELECT * FROM Dives;").Rows.Count);
            Assert.AreEqual(0, DbHandler.Instance.DbEngine.SqlQuery("SELECT * FROM DiveScores;").Rows.Count);
            Assert.AreEqual(3, DbHandler.Instance.DbEngine.SqlQuery("SELECT * FROM Persons;").Rows.Count);

            UnitTestMockObjects._contest1.Country = "Sweden";
            UnitTestMockObjects._contest1.Status = ContestStatus.Unstarted;

            DbHandler.Instance.SaveCompleteContestToDb(UnitTestMockObjects._contest1);
            ds = DbHandler.Instance.DbEngine.SqlQuery("SELECT * FROM Contests;").Rows;

            Assert.AreEqual(1, ds.Count);
            Assert.AreEqual(UnitTestMockObjects._contest1.Name, (string)ds[0]["Name"]);
            Assert.AreEqual(UnitTestMockObjects._contest1.Country, (string)ds[0]["Country"]);
            Assert.AreEqual(UnitTestMockObjects._contest1.City, (string)ds[0]["City"]);
            Assert.AreEqual(UnitTestMockObjects._contest1.Club, (string)ds[0]["Club"]);
            Assert.AreEqual(UnitTestMockObjects._contest1.Date, (string)ds[0]["Date"]);
            Assert.AreEqual(UnitTestMockObjects._contest1.JudgeList.NumberOfJudges, Convert.ToInt32(ds[0]["NumJudges"]));
            Assert.AreEqual(UnitTestMockObjects._contest1.Status, (ContestStatus)Enum.Parse(typeof(ContestStatus), (string)ds[0]["Status"]));

            Assert.AreEqual(3, DbHandler.Instance.DbEngine.SqlQuery("SELECT * FROM Judges;").Rows.Count);
            Assert.AreEqual(0, DbHandler.Instance.DbEngine.SqlQuery("SELECT * FROM Dives;").Rows.Count);
            Assert.AreEqual(0, DbHandler.Instance.DbEngine.SqlQuery("SELECT * FROM DiveScores;").Rows.Count);
            Assert.AreEqual(3, DbHandler.Instance.DbEngine.SqlQuery("SELECT * FROM Persons;").Rows.Count);
        }

        [Test]
        public void DbHandlerSaveContestWithLists()
        {
            DbHandler.Instance.SaveCompleteContestToDb(UnitTestMockObjects._contest1);
            
            Assert.AreEqual(3, DbHandler.Instance.DbEngine.SqlQuery("SELECT * FROM Judges;").Rows.Count);
            Assert.AreEqual(6, DbHandler.Instance.DbEngine.SqlQuery("SELECT * FROM Dives;").Rows.Count);
            Assert.AreEqual(9, DbHandler.Instance.DbEngine.SqlQuery("SELECT * FROM DiveScores;").Rows.Count);
            Assert.AreEqual(6, DbHandler.Instance.DbEngine.SqlQuery("SELECT * FROM Persons;").Rows.Count);

            UnitTestMockObjects._contest1.Country = "Sweden";
            UnitTestMockObjects._contest1.Status = ContestStatus.Unstarted;
            UnitTestMockObjects._contest1.DiveQueue[0].DiveScoreList.Add(new DiveScore
            {
                Judge = UnitTestMockObjects._judge1,
                Score = 4.5
            });

            DbHandler.Instance.SaveCompleteContestToDb(UnitTestMockObjects._contest1);

            Assert.AreEqual(3, DbHandler.Instance.DbEngine.SqlQuery("SELECT * FROM Judges;").Rows.Count);
            Assert.AreEqual(6, DbHandler.Instance.DbEngine.SqlQuery("SELECT * FROM Dives;").Rows.Count);
            Assert.AreEqual(10, DbHandler.Instance.DbEngine.SqlQuery("SELECT * FROM DiveScores;").Rows.Count);
            Assert.AreEqual(6, DbHandler.Instance.DbEngine.SqlQuery("SELECT * FROM Persons;").Rows.Count);
        }

        [Test]
        public void DbHandlerLoadContestClearLists()
        {
            UnitTestMockObjects._contest1.DiveHistory = new DiveList();
            UnitTestMockObjects._contest1.DiveQueue = new DiveList();
            DbHandler.Instance.SaveCompleteContestToDb(UnitTestMockObjects._contest1);
            var contest2 = DbHandler.Instance.LoadContestFromDb(1);

            Assert.AreEqual(UnitTestMockObjects._contest1.City, contest2.City);
            Assert.AreEqual(UnitTestMockObjects._contest1.Club, contest2.Club);
            Assert.AreEqual(UnitTestMockObjects._contest1.Country, contest2.Country);
            Assert.AreEqual(UnitTestMockObjects._contest1.Date, contest2.Date);
            Assert.AreEqual(UnitTestMockObjects._contest1.DiveHistory.Count, contest2.DiveHistory.Count);
            Assert.AreEqual(UnitTestMockObjects._contest1.DiveQueue.Count, contest2.DiveQueue.Count);
            Assert.AreEqual(UnitTestMockObjects._contest1.JudgeList.NumberOfJudges, contest2.JudgeList.NumberOfJudges);
            Assert.AreEqual(UnitTestMockObjects._contest1.JudgeList.Count, contest2.JudgeList.Count);
            Assert.AreEqual(UnitTestMockObjects._contest1.Name, contest2.Name);
            Assert.AreEqual(UnitTestMockObjects._contest1.Status, contest2.Status);
        }

        [Test]
        public void DbHandlerLoadContestWithLists()
        {
            DbHandler.Instance.SaveCompleteContestToDb(UnitTestMockObjects._contest1);
            var contest2 = DbHandler.Instance.LoadContestFromDb(1);

            Assert.AreEqual(UnitTestMockObjects._contest1.City, contest2.City);
            Assert.AreEqual(UnitTestMockObjects._contest1.Club, contest2.Club);
            Assert.AreEqual(UnitTestMockObjects._contest1.Country, contest2.Country);
            Assert.AreEqual(UnitTestMockObjects._contest1.Date, contest2.Date);
            Assert.AreEqual(UnitTestMockObjects._contest1.DiveHistory.Count, contest2.DiveHistory.Count);
            Assert.AreEqual(UnitTestMockObjects._contest1.DiveQueue.Count, contest2.DiveQueue.Count);
            Assert.AreEqual(UnitTestMockObjects._contest1.JudgeList.NumberOfJudges, contest2.JudgeList.NumberOfJudges);
            Assert.AreEqual(UnitTestMockObjects._contest1.JudgeList.Count, contest2.JudgeList.Count);
            Assert.AreEqual(UnitTestMockObjects._contest1.Name, contest2.Name);
            Assert.AreEqual(UnitTestMockObjects._contest1.Status, contest2.Status);
            Assert.AreEqual(UnitTestMockObjects._dive22.Diver.IdNumber, contest2.DiveQueue[1].Diver.IdNumber);
        }

        [Test]
        public void DbHandlerResetContest()
        {
            DbHandler.Instance.SaveCompleteContestToDb(UnitTestMockObjects._contest1);
            var contest2 = DbHandler.Instance.ResetContest(1);

            Assert.AreEqual(UnitTestMockObjects._contest1.City, contest2.City);
            Assert.AreEqual(UnitTestMockObjects._contest1.Club, contest2.Club);
            Assert.AreEqual(UnitTestMockObjects._contest1.Country, contest2.Country);
            Assert.AreEqual(UnitTestMockObjects._contest1.Date, contest2.Date);
            Assert.AreEqual(0, contest2.DiveHistory.Count);
            Assert.AreEqual(6, contest2.DiveQueue.Count);
            Assert.AreEqual(UnitTestMockObjects._contest1.JudgeList.NumberOfJudges, contest2.JudgeList.NumberOfJudges);
            Assert.AreEqual(UnitTestMockObjects._contest1.JudgeList.Count, contest2.JudgeList.Count);
            Assert.AreEqual(UnitTestMockObjects._contest1.Name, contest2.Name);
            Assert.AreEqual(ContestStatus.Unstarted, contest2.Status);

            Assert.AreEqual(0, DbHandler.Instance.DbEngine.SqlQuery("SELECT * FROM DiveScores;").Rows.Count);
        }

        [Test]
        public void DbHandlerSetContestStatus()
        {
            DbHandler.Instance.SaveCompleteContestToDb(UnitTestMockObjects._contest1);
            DbHandler.Instance.SetContestStatus(ContestStatus.Finished, 1);
            var contest2 = DbHandler.Instance.LoadContestFromDb(1);

            Assert.AreEqual(UnitTestMockObjects._contest1.City, contest2.City);
            Assert.AreEqual(UnitTestMockObjects._contest1.Club, contest2.Club);
            Assert.AreEqual(UnitTestMockObjects._contest1.Country, contest2.Country);
            Assert.AreEqual(UnitTestMockObjects._contest1.Date, contest2.Date);
            Assert.AreEqual(UnitTestMockObjects._contest1.DiveHistory.Count, contest2.DiveHistory.Count);
            Assert.AreEqual(UnitTestMockObjects._contest1.DiveQueue.Count, contest2.DiveQueue.Count);
            Assert.AreEqual(UnitTestMockObjects._contest1.JudgeList.NumberOfJudges, contest2.JudgeList.NumberOfJudges);
            Assert.AreEqual(UnitTestMockObjects._contest1.JudgeList.Count, contest2.JudgeList.Count);
            Assert.AreEqual(UnitTestMockObjects._contest1.Name, contest2.Name);
            Assert.AreEqual(ContestStatus.Finished, contest2.Status);
        }

        [Test]
        public void DbHandlerDeleteContest()
        {
            DbHandler.Instance.SaveCompleteContestToDb(UnitTestMockObjects._contest1);
            DbHandler.Instance.DeleteContest(ref UnitTestMockObjects._contest1);

            Assert.AreEqual(0, DbHandler.Instance.DbEngine.SqlQuery("SELECT * FROM Judges;").Rows.Count);
            Assert.AreEqual(0, DbHandler.Instance.DbEngine.SqlQuery("SELECT * FROM Dives;").Rows.Count);
            Assert.AreEqual(0, DbHandler.Instance.DbEngine.SqlQuery("SELECT * FROM DiveScores;").Rows.Count);
            Assert.AreEqual(6, DbHandler.Instance.DbEngine.SqlQuery("SELECT * FROM Persons;").Rows.Count);
            Assert.AreEqual(0, DbHandler.Instance.DbEngine.SqlQuery("SELECT * FROM Contests;").Rows.Count);
            Assert.IsNull(UnitTestMockObjects._contest1);
        }

        [Test]
        public void DbHandlerSaveDiveScoreToDb()
        {
            DbHandler.Instance.SaveCompleteContestToDb(UnitTestMockObjects._contest1);
            var divescore = new DiveScore
            {
                Judge = UnitTestMockObjects._judge1,
                Score = 4.5
            };
            DbHandler.Instance.SaveDiveScoreToDb(divescore, UnitTestMockObjects._dive12);
            Assert.AreEqual(1, DbHandler.Instance.DbEngine.SqlQuery("SELECT * FROM DiveScores WHERE Dive = " + UnitTestMockObjects._dive12.DbId + ";").Rows.Count);
        }

        [Test]
        public void DbHandlerDeleteDive()
        {
            DbHandler.Instance.SaveCompleteContestToDb(UnitTestMockObjects._contest1);
            DbHandler.Instance.DeleteDive(UnitTestMockObjects._dive11);

            Assert.AreEqual(5, DbHandler.Instance.DbEngine.SqlQuery("SELECT * FROM Dives;").Rows.Count);
            Assert.AreEqual(6, DbHandler.Instance.DbEngine.SqlQuery("SELECT * FROM DiveScores;").Rows.Count);
        }

        [Test]
        public void DbHandlerDeleteJudge()
        {
            DbHandler.Instance.SaveCompleteContestToDb(UnitTestMockObjects._contest1);
            DbHandler.Instance.DeleteJudge(UnitTestMockObjects._judge1);

            Assert.AreEqual(2, DbHandler.Instance.DbEngine.SqlQuery("SELECT * FROM Judges;").Rows.Count);
        }

        [Test]
        public void DbHandlerDeleteDiver()
        {
            DbHandler.Instance.SaveCompleteContestToDb(UnitTestMockObjects._contest1);
            DbHandler.Instance.DeleteDiver(UnitTestMockObjects._diver1);

            Assert.AreEqual(3, DbHandler.Instance.DbEngine.SqlQuery("SELECT * FROM Judges;").Rows.Count);
            Assert.AreEqual(4, DbHandler.Instance.DbEngine.SqlQuery("SELECT * FROM Dives;").Rows.Count);
            Assert.AreEqual(6, DbHandler.Instance.DbEngine.SqlQuery("SELECT * FROM DiveScores;").Rows.Count);
        }

        [Test]
        public void DbHandlerLoadContestList()
        {
            DbHandler.Instance.SaveCompleteContestToDb(UnitTestMockObjects._contest1);
            UnitTestMockObjects._contest1.Club = "Finnspång motorsågsklubb";
            UnitTestMockObjects._contest1.Date = "2015-03-13";
            UnitTestMockObjects._contest1.DbId = null;
            UnitTestMockObjects._contest1.Name = "Hoppalong";
            UnitTestMockObjects._contest1.JudgeList = new JudgeList();
            UnitTestMockObjects._contest1.DiveQueue = new DiveList();
            UnitTestMockObjects._contest1.DiveHistory = new DiveList();
            DbHandler.Instance.SaveCompleteContestToDb(UnitTestMockObjects._contest1);
            var contestList = DbHandler.Instance.LoadContestList(false, false);
            Assert.AreEqual(2, contestList.Count);
        }

        [SetUp]
        public void SetUpFunc()
        {
            var customCulture = (System.Globalization.CultureInfo)Thread.CurrentThread.CurrentCulture.Clone();
            customCulture.NumberFormat.NumberDecimalSeparator = ".";

            Thread.CurrentThread.CurrentCulture = customCulture;
            UnitTestMockObjects.ResetDatabase();
            UnitTestMockObjects.ResetObjects();
        }

    }
}
